use crate::error::TauriCommandError;
use crate::types::{FileChange, ChangeType};
use notify::{Watcher, RecursiveMode, Event, EventKind};
use std::path::Path;
use std::sync::mpsc;
use std::thread;
use dashmap::DashMap;
use std::sync::Arc;

/// 文件监控器信息
#[derive(Debug)]
pub struct WatcherInfo {
    pub id: String,
    pub path: String,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub is_active: bool,
}

/// 文件监控服务
pub struct WatcherService {
    watchers: Arc<DashMap<String, WatcherInfo>>,
    change_sender: tokio::sync::broadcast::Sender<FileChange>,
}

impl WatcherService {
    /// 创建新的监控服务
    pub fn new() -> Self {
        let (change_sender, _) = tokio::sync::broadcast::channel(1000);
        
        Self {
            watchers: Arc::new(DashMap::new()),
            change_sender,
        }
    }
    
    /// 开始监控目录
    pub async fn start_watching(&self, path: &str) -> Result<String, TauriCommandError> {
        let watch_path = Path::new(path);
        
        if !watch_path.exists() {
            return Err(TauriCommandError::file_system("监控路径不存在"));
        }
        
        if !watch_path.is_dir() {
            return Err(TauriCommandError::file_system("监控路径必须是目录"));
        }
        
        let watcher_id = uuid::Uuid::new_v4().to_string();
        let watcher_info = WatcherInfo {
            id: watcher_id.clone(),
            path: path.to_string(),
            created_at: chrono::Utc::now(),
            is_active: true,
        };
        
        // 存储监控器信息
        self.watchers.insert(watcher_id.clone(), watcher_info);
        
        // 启动文件监控
        let path_clone = path.to_string();
        let watcher_id_clone = watcher_id.clone();
        let change_sender = self.change_sender.clone();
        let watchers = self.watchers.clone();
        
        tokio::spawn(async move {
            if let Err(e) = Self::run_watcher(&path_clone, &watcher_id_clone, change_sender, watchers).await {
                log::error!("File watcher error for {}: {}", path_clone, e);
            }
        });
        
        log::info!("Started file watcher for: {} (ID: {})", path, watcher_id);
        Ok(watcher_id)
    }
    
    /// 停止监控
    pub async fn stop_watching(&self, watcher_id: &str) -> Result<(), TauriCommandError> {
        if let Some(mut watcher) = self.watchers.get_mut(watcher_id) {
            watcher.is_active = false;
            log::info!("Stopped file watcher: {}", watcher_id);
            Ok(())
        } else {
            Err(TauriCommandError::file_system("监控器不存在"))
        }
    }
    
    /// 获取所有监控器
    pub fn get_watchers(&self) -> Vec<WatcherInfo> {
        self.watchers.iter()
            .map(|entry| {
                let watcher = entry.value();
                WatcherInfo {
                    id: watcher.id.clone(),
                    path: watcher.path.clone(),
                    created_at: watcher.created_at,
                    is_active: watcher.is_active,
                }
            })
            .collect()
    }
    
    /// 订阅文件变更事件
    pub fn subscribe_changes(&self) -> tokio::sync::broadcast::Receiver<FileChange> {
        self.change_sender.subscribe()
    }
    
    /// 清理非活跃的监控器
    pub fn cleanup_inactive(&self) {
        self.watchers.retain(|_, watcher| watcher.is_active);
    }
    
    /// 运行文件监控器
    async fn run_watcher(
        path: &str,
        watcher_id: &str,
        change_sender: tokio::sync::broadcast::Sender<FileChange>,
        watchers: Arc<DashMap<String, WatcherInfo>>,
    ) -> Result<(), TauriCommandError> {
        let (tx, rx) = mpsc::channel();
        
        // 创建文件监控器
        let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
            match res {
                Ok(event) => {
                    if let Err(e) = tx.send(event) {
                        log::error!("Failed to send file event: {}", e);
                    }
                }
                Err(e) => log::error!("File watch error: {}", e),
            }
        }).map_err(|e| TauriCommandError::io(format!("创建文件监控器失败: {}", e)))?;
        
        // 开始监控
        watcher.watch(Path::new(path), RecursiveMode::Recursive)
            .map_err(|e| TauriCommandError::io(format!("启动文件监控失败: {}", e)))?;
        
        // 处理文件事件
        let watcher_id_clone = watcher_id.to_string();
        thread::spawn(move || {
            while let Ok(event) = rx.recv() {
                // 检查监控器是否仍然活跃
                if let Some(watcher_info) = watchers.get(&watcher_id_clone) {
                    if !watcher_info.is_active {
                        break;
                    }
                } else {
                    break;
                }
                
                // 处理文件事件
                if let Some(file_change) = Self::process_file_event(event) {
                    if let Err(e) = change_sender.send(file_change) {
                        log::warn!("Failed to broadcast file change: {}", e);
                    }
                }
            }
            
            log::info!("File watcher thread stopped for: {}", watcher_id_clone);
        });
        
        Ok(())
    }
    
    /// 处理文件事件
    fn process_file_event(event: Event) -> Option<FileChange> {
        let paths = event.paths;
        if paths.is_empty() {
            return None;
        }
        
        let path = paths[0].to_string_lossy().to_string();
        
        // 过滤不需要的文件
        if crate::utils::should_ignore_file(&path) {
            return None;
        }
        
        let change_type = match event.kind {
            EventKind::Create(_) => ChangeType::Created,
            EventKind::Modify(_) => ChangeType::Modified,
            EventKind::Remove(_) => ChangeType::Deleted,
            _ => return None,
        };
        
        // 读取文件内容（如果是创建或修改事件）
        let content = match change_type {
            ChangeType::Created | ChangeType::Modified => {
                if Path::new(&path).is_file() {
                    std::fs::read_to_string(&path).ok()
                } else {
                    None
                }
            }
            _ => None,
        };
        
        Some(FileChange {
            path,
            change_type,
            content,
            timestamp: chrono::Utc::now(),
        })
    }
}

impl Default for WatcherService {
    fn default() -> Self {
        Self::new()
    }
}

// 全局文件监控服务实例
lazy_static::lazy_static! {
    pub static ref WATCHER_SERVICE: WatcherService = WatcherService::new();
}

/// 文件变更事件处理器
pub struct FileChangeHandler;

impl FileChangeHandler {
    /// 处理文件变更事件
    pub async fn handle_change(change: FileChange) -> Result<(), TauriCommandError> {
        log::debug!("Handling file change: {} ({:?})", change.path, change.change_type);
        
        // 根据变更类型执行相应操作
        match change.change_type {
            ChangeType::Created => {
                Self::handle_file_created(&change).await?;
            }
            ChangeType::Modified => {
                Self::handle_file_modified(&change).await?;
            }
            ChangeType::Deleted => {
                Self::handle_file_deleted(&change).await?;
            }
            ChangeType::Renamed { ref old_path } => {
                Self::handle_file_renamed(old_path, &change.path).await?;
            }
        }
        
        Ok(())
    }
    
    async fn handle_file_created(change: &FileChange) -> Result<(), TauriCommandError> {
        log::debug!("File created: {}", change.path);
        
        // 如果是源代码文件，触发增量解析
        if crate::utils::is_source_file(&change.path) {
            // TODO: 触发 CodeGraph 增量更新
        }
        
        Ok(())
    }
    
    async fn handle_file_modified(change: &FileChange) -> Result<(), TauriCommandError> {
        log::debug!("File modified: {}", change.path);
        
        // 如果是源代码文件，触发增量解析
        if crate::utils::is_source_file(&change.path) {
            // TODO: 触发 CodeGraph 增量更新
        }
        
        Ok(())
    }
    
    async fn handle_file_deleted(change: &FileChange) -> Result<(), TauriCommandError> {
        log::debug!("File deleted: {}", change.path);
        
        // 如果是源代码文件，从图谱中移除相关节点
        if crate::utils::is_source_file(&change.path) {
            // TODO: 从 CodeGraph 中移除节点
        }
        
        Ok(())
    }
    
    async fn handle_file_renamed(old_path: &str, new_path: &str) -> Result<(), TauriCommandError> {
        log::debug!("File renamed: {} -> {}", old_path, new_path);
        
        // 如果是源代码文件，更新图谱中的路径信息
        if crate::utils::is_source_file(old_path) || crate::utils::is_source_file(new_path) {
            // TODO: 更新 CodeGraph 中的路径信息
        }
        
        Ok(())
    }
}
